import pivotTable from "../controllers/pivotTable";
import conditionformat from "../controllers/conditionformat";
import alternateformat from "../controllers/alternateformat";
import luckysheetSparkline from "../controllers/sparkline";
import menuButton from "../controllers/menuButton";
import dataVerificationCtrl from "../controllers/dataVerificationCtrl";
import {
	luckysheetdefaultstyle,
	luckysheet_CFiconsImg,
	luckysheetdefaultFont,
} from "../controllers/constant";
import { luckysheet_searcharray } from "../controllers/sheetSearch";
import { dynamicArrayCompute } from "./dynamicArray";
import browser from "./browser";
import { isRealNull, isRealNum } from "./validate";
import { getMeasureText, getCellTextInfo } from "./getRowlen";
import { getRealCellValue } from "./getdata";
import { getBorderInfoComputeRange } from "./border";
import { getSheetIndex } from "../methods/get";
import { getObjType, chatatABC, luckysheetfontformat } from "../utils/util";
import { isInlineStringCell } from "../controllers/inlineString";
import method from "./method";
import Store from "../store";
import locale from "../locale/locale";
import sheetmanage from "../controllers/sheetmanage";

function luckysheetDrawgridRowTitle(scrollHeight, drawHeight, offsetTop) {
	if (scrollHeight == null) {
		scrollHeight = $("#luckysheet-cell-main").scrollTop();
	}

	if (drawHeight == null) {
		drawHeight = Store.luckysheetTableContentHW[1];
	}

	if (offsetTop == null) {
		offsetTop = Store.columnHeaderHeight;
	}

	let luckysheetTableContent = $("#luckysheetTableContent")
		.get(0)
		.getContext("2d");
	luckysheetTableContent.save();
	luckysheetTableContent.scale(Store.devicePixelRatio, Store.devicePixelRatio);

	luckysheetTableContent.clearRect(
		0,
		offsetTop,
		Store.rowHeaderWidth - 1,
		drawHeight
	);

	luckysheetTableContent.font = luckysheetdefaultFont();
	luckysheetTableContent.textBaseline = luckysheetdefaultstyle.textBaseline; //基准线 垂直居中
	luckysheetTableContent.fillStyle = luckysheetdefaultstyle.fillStyle;

	let dataset_row_st, dataset_row_ed;
	dataset_row_st = luckysheet_searcharray(Store.visibledatarow, scrollHeight);
	dataset_row_ed = luckysheet_searcharray(
		Store.visibledatarow,
		scrollHeight + drawHeight
	);

	if (dataset_row_st == -1) {
		dataset_row_st = 0;
	}
	if (dataset_row_ed == -1) {
		dataset_row_ed = Store.visibledatarow.length - 1;
	}

	luckysheetTableContent.save();
	luckysheetTableContent.beginPath();
	luckysheetTableContent.rect(
		0,
		offsetTop - 1,
		Store.rowHeaderWidth - 1,
		drawHeight - 2
	);
	luckysheetTableContent.clip();

	let end_r, start_r;
	let bodrder05 = 0.5; //Default 0.5
	let preEndR;
	for (let r = dataset_row_st; r <= dataset_row_ed; r++) {
		if (r == 0) {
			start_r = -scrollHeight - 1;
		} else {
			start_r = Store.visibledatarow[r - 1] - scrollHeight - 1;
		}
		end_r = Store.visibledatarow[r] - scrollHeight;

		//若超出绘制区域终止
		// if(end_r > scrollHeight + drawHeight){
		//     break;
		// }
		let firstOffset = dataset_row_st == r ? -2 : 0;
		let lastOffset = dataset_row_ed == r ? -2 : 0;
		//列标题单元格渲染前触发，return false 则不渲染该单元格
		if (
			!method.createHookFunction(
				"rowTitleCellRenderBefore",
				r + 1,
				{
					r: r,
					top: start_r + offsetTop + firstOffset,
					width: Store.rowHeaderWidth - 1,
					height: end_r - start_r + 1 + lastOffset - firstOffset,
				},
				luckysheetTableContent
			)
		) {
			continue;
		}

		if (
			Store.config["rowhidden"] != null &&
			Store.config["rowhidden"][r] != null
		) {
		} else {
			luckysheetTableContent.fillStyle = "#ffffff";
			luckysheetTableContent.fillRect(
				0,
				start_r + offsetTop + firstOffset,
				Store.rowHeaderWidth - 1,
				end_r - start_r + 1 + lastOffset - firstOffset
			);
			luckysheetTableContent.fillStyle = "#000000";

			//行标题栏序列号
			luckysheetTableContent.save(); //save scale before draw text
			luckysheetTableContent.scale(Store.zoomRatio, Store.zoomRatio);
			let textMetrics = getMeasureText(r + 1, luckysheetTableContent);
			//luckysheetTableContent.measureText(r + 1);

			let horizonAlignPos = (Store.rowHeaderWidth - textMetrics.width) / 2;
			let verticalAlignPos = start_r + (end_r - start_r) / 2 + offsetTop;

			luckysheetTableContent.fillText(
				r + 1,
				horizonAlignPos / Store.zoomRatio,
				verticalAlignPos / Store.zoomRatio
			);
			luckysheetTableContent.restore(); //restore scale after draw text
		}

		//vertical
		luckysheetTableContent.beginPath();
		luckysheetTableContent.moveTo(
			Store.rowHeaderWidth - 2 + bodrder05,
			start_r + offsetTop - 2
		);
		luckysheetTableContent.lineTo(
			Store.rowHeaderWidth - 2 + bodrder05,
			end_r + offsetTop - 2
		);
		luckysheetTableContent.lineWidth = 1;

		luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
		luckysheetTableContent.stroke();
		luckysheetTableContent.closePath();

		//行标题栏横线,horizen
		if (
			Store.config["rowhidden"] != null &&
			Store.config["rowhidden"][r] == null &&
			Store.config["rowhidden"][r + 1] != null
		) {
			luckysheetTableContent.beginPath();
			luckysheetTableContent.moveTo(-1, end_r + offsetTop - 4 + bodrder05);
			luckysheetTableContent.lineTo(
				Store.rowHeaderWidth - 1,
				end_r + offsetTop - 4 + bodrder05
			);
			// luckysheetTableContent.lineWidth = 1;
			// luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
			luckysheetTableContent.closePath();
			luckysheetTableContent.stroke();
		} else if (
			Store.config["rowhidden"] == null ||
			Store.config["rowhidden"][r] == null
		) {
			luckysheetTableContent.beginPath();
			luckysheetTableContent.moveTo(-1, end_r + offsetTop - 2 + bodrder05);
			luckysheetTableContent.lineTo(
				Store.rowHeaderWidth - 1,
				end_r + offsetTop - 2 + bodrder05
			);

			// luckysheetTableContent.lineWidth = 1;
			// luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
			luckysheetTableContent.closePath();
			luckysheetTableContent.stroke();
		}

		if (
			Store.config["rowhidden"] != null &&
			Store.config["rowhidden"][r - 1] != null &&
			preEndR != null
		) {
			luckysheetTableContent.beginPath();
			luckysheetTableContent.moveTo(-1, preEndR + offsetTop + bodrder05);
			luckysheetTableContent.lineTo(
				Store.rowHeaderWidth - 1,
				preEndR + offsetTop + bodrder05
			);
			luckysheetTableContent.closePath();
			luckysheetTableContent.stroke();
		}

		preEndR = end_r;

		//列标题单元格渲染前触发，return false 则不渲染该单元格
		method.createHookFunction(
			"rowTitleCellRenderAfter",
			r + 1,
			{
				r: r,
				top: start_r + offsetTop + firstOffset,
				width: Store.rowHeaderWidth - 1,
				height: end_r - start_r + 1 + lastOffset - firstOffset,
			},
			luckysheetTableContent
		);
	}

	//行标题栏竖线
	// luckysheetTableContent.beginPath();
	// luckysheetTableContent.moveTo(
	//     (Store.rowHeaderWidth - 2 + 0.5) ,
	//     (offsetTop - 1)
	// );
	// luckysheetTableContent.lineTo(
	//     (Store.rowHeaderWidth - 2 + 0.5) ,
	//     (Store.rh_height + offsetTop)
	// );
	// luckysheetTableContent.lineWidth = 1;
	// luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
	// luckysheetTableContent.closePath();
	// luckysheetTableContent.stroke();

	//清除canvas左上角区域 防止列标题栏序列号溢出显示
	// luckysheetTableContent.clearRect(0, 0, Store.rowHeaderWidth , Store.columnHeaderHeight );

	// Must be restored twice, otherwise it will be enlarged under window.devicePixelRatio = 1.5
	luckysheetTableContent.restore();
	luckysheetTableContent.restore();
}

function luckysheetDrawgridColumnTitle(scrollWidth, drawWidth, offsetLeft) {
	if (scrollWidth == null) {
		scrollWidth = $("#luckysheet-cell-main").scrollLeft();
	}

	if (drawWidth == null) {
		drawWidth = Store.luckysheetTableContentHW[0];
	}

	if (offsetLeft == null) {
		offsetLeft = Store.rowHeaderWidth;
	}

	let luckysheetTableContent = $("#luckysheetTableContent")
		.get(0)
		.getContext("2d");
	luckysheetTableContent.save();
	luckysheetTableContent.scale(Store.devicePixelRatio, Store.devicePixelRatio);
	luckysheetTableContent.clearRect(
		offsetLeft,
		0,
		drawWidth,
		Store.columnHeaderHeight - 1
	);

	luckysheetTableContent.font = luckysheetdefaultFont();
	luckysheetTableContent.textBaseline = luckysheetdefaultstyle.textBaseline; //基准线 垂直居中
	luckysheetTableContent.fillStyle = luckysheetdefaultstyle.fillStyle;

	let dataset_col_st, dataset_col_ed;
	dataset_col_st = luckysheet_searcharray(Store.visibledatacolumn, scrollWidth);
	dataset_col_ed = luckysheet_searcharray(
		Store.visibledatacolumn,
		scrollWidth + drawWidth
	);

	if (dataset_col_st == -1) {
		dataset_col_st = 0;
	}
	if (dataset_col_ed == -1) {
		dataset_col_ed = Store.visibledatacolumn.length - 1;
	}

	luckysheetTableContent.save();
	luckysheetTableContent.beginPath();
	luckysheetTableContent.rect(
		offsetLeft - 1,
		0,
		drawWidth,
		Store.columnHeaderHeight - 1
	);
	luckysheetTableContent.clip();

	// console.log(offsetLeft, 0, drawWidth, Store.columnHeaderHeight -1);

	let end_c, start_c;
	let bodrder05 = 0.5; //Default 0.5
	let preEndC;
	for (let c = dataset_col_st; c <= dataset_col_ed; c++) {
		if (c == 0) {
			start_c = -scrollWidth;
		} else {
			start_c = Store.visibledatacolumn[c - 1] - scrollWidth;
		}
		end_c = Store.visibledatacolumn[c] - scrollWidth;

		//若超出绘制区域终止
		// if(end_c > scrollWidth + drawWidth+1){
		//     break;
		// }
		let abc = chatatABC(c);
		//列标题单元格渲染前触发，return false 则不渲染该单元格
		if (
			!method.createHookFunction(
				"columnTitleCellRenderBefore",
				abc,
				{
					c: c,
					left: start_c + offsetLeft - 1,
					width: end_c - start_c,
					height: Store.columnHeaderHeight - 1,
				},
				luckysheetTableContent
			)
		) {
			continue;
		}

		if (
			Store.config["colhidden"] != null &&
			Store.config["colhidden"][c] != null
		) {
		} else {
			luckysheetTableContent.fillStyle = "#ffffff";
			luckysheetTableContent.fillRect(
				start_c + offsetLeft - 1,
				0,
				end_c - start_c,
				Store.columnHeaderHeight - 1
			);
			luckysheetTableContent.fillStyle = "#000000";

			//列标题栏序列号
			luckysheetTableContent.save(); //save scale before draw text
			luckysheetTableContent.scale(Store.zoomRatio, Store.zoomRatio);

			let textMetrics = getMeasureText(abc, luckysheetTableContent);
			//luckysheetTableContent.measureText(abc);

			let horizonAlignPos = Math.round(
				start_c + (end_c - start_c) / 2 + offsetLeft - textMetrics.width / 2
			);
			let verticalAlignPos = Math.round(Store.columnHeaderHeight / 2);

			luckysheetTableContent.fillText(
				abc,
				horizonAlignPos / Store.zoomRatio,
				verticalAlignPos / Store.zoomRatio
			);
			luckysheetTableContent.restore(); //restore scale after draw text
		}

		//列标题栏竖线 vertical
		if (
			Store.config["colhidden"] != null &&
			Store.config["colhidden"][c] == null &&
			Store.config["colhidden"][c + 1] != null
		) {
			luckysheetTableContent.beginPath();
			luckysheetTableContent.moveTo(end_c + offsetLeft - 4 + bodrder05, 0);
			luckysheetTableContent.lineTo(
				end_c + offsetLeft - 4 + bodrder05,
				Store.columnHeaderHeight - 2
			);
			luckysheetTableContent.lineWidth = 1;
			luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
			luckysheetTableContent.closePath();
			luckysheetTableContent.stroke();
		} else if (
			Store.config["colhidden"] == null ||
			Store.config["colhidden"][c] == null
		) {
			luckysheetTableContent.beginPath();
			luckysheetTableContent.moveTo(end_c + offsetLeft - 2 + bodrder05, 0);
			luckysheetTableContent.lineTo(
				end_c + offsetLeft - 2 + bodrder05,
				Store.columnHeaderHeight - 2
			);

			luckysheetTableContent.lineWidth = 1;
			luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
			luckysheetTableContent.closePath();
			luckysheetTableContent.stroke();
		}

		if (
			Store.config["colhidden"] != null &&
			Store.config["colhidden"][c - 1] != null &&
			preEndC != null
		) {
			luckysheetTableContent.beginPath();
			luckysheetTableContent.moveTo(preEndC + offsetLeft + bodrder05, 0);
			luckysheetTableContent.lineTo(
				preEndC + offsetLeft + bodrder05,
				Store.columnHeaderHeight - 2
			);
			// luckysheetTableContent.lineWidth = 1;
			// luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
			luckysheetTableContent.closePath();
			luckysheetTableContent.stroke();
		}

		//horizen
		luckysheetTableContent.beginPath();
		luckysheetTableContent.moveTo(
			start_c + offsetLeft - 1,
			Store.columnHeaderHeight - 2 + bodrder05
		);
		luckysheetTableContent.lineTo(
			end_c + offsetLeft - 1,
			Store.columnHeaderHeight - 2 + bodrder05
		);
		// luckysheetTableContent.lineWidth = 1;

		// luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
		luckysheetTableContent.stroke();
		luckysheetTableContent.closePath();

		preEndC = end_c;

		method.createHookFunction(
			"columnTitleCellRenderAfter",
			abc,
			{
				c: c,
				left: start_c + offsetLeft - 1,
				width: end_c - start_c,
				height: Store.columnHeaderHeight - 1,
			},
			luckysheetTableContent
		);
	}

	//列标题栏横线
	// luckysheetTableContent.beginPath();
	// luckysheetTableContent.moveTo(
	//     (offsetLeft - 1) ,
	//     (Store.columnHeaderHeight - 2 + 0.5)
	// );
	// luckysheetTableContent.lineTo(
	//     (Store.ch_width + offsetLeft - 2) ,
	//     (Store.columnHeaderHeight - 2 + 0.5)
	// );
	// luckysheetTableContent.lineWidth = 1;
	// luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
	// luckysheetTableContent.closePath();
	// luckysheetTableContent.stroke();

	//清除canvas左上角区域 防止列标题栏序列号溢出显示
	// luckysheetTableContent.clearRect(0, 0, Store.rowHeaderWidth , Store.columnHeaderHeight );

	// Must be restored twice, otherwise it will be enlarged under window.devicePixelRatio = 1.5
	luckysheetTableContent.restore();
	luckysheetTableContent.restore();
}

function luckysheetDrawMain(
	scrollWidth,
	scrollHeight,
	drawWidth,
	drawHeight,
	offsetLeft,
	offsetTop,
	columnOffsetCell,
	rowOffsetCell,
	mycanvas
) {
	if (Store.flowdata == null) {
		return;
	}

	let sheetFile = sheetmanage.getSheetByIndex();

	// console.trace();
	clearTimeout(Store.measureTextCacheTimeOut);

	//参数未定义处理
	if (scrollWidth == null) {
		scrollWidth = $("#luckysheet-cell-main").scrollLeft();
	}
	if (scrollHeight == null) {
		scrollHeight = $("#luckysheet-cell-main").scrollTop();
	}

	if (drawWidth == null) {
		drawWidth = Store.luckysheetTableContentHW[0];
	}
	if (drawHeight == null) {
		drawHeight = Store.luckysheetTableContentHW[1];
	}

	if (offsetLeft == null) {
		offsetLeft = Store.rowHeaderWidth;
	}
	if (offsetTop == null) {
		offsetTop = Store.columnHeaderHeight;
	}

	if (columnOffsetCell == null) {
		columnOffsetCell = 0;
	}
	if (rowOffsetCell == null) {
		rowOffsetCell = 0;
	}

	//表格canvas
	let luckysheetTableContent = null;
	if (mycanvas == null) {
		luckysheetTableContent = $("#luckysheetTableContent")
			.get(0)
			.getContext("2d");
	} else {
		if (getObjType(mycanvas) == "object") {
			try {
				luckysheetTableContent = mycanvas.get(0).getContext("2d");
			} catch (err) {
				luckysheetTableContent = mycanvas;
			}
		} else {
			luckysheetTableContent = $("#" + mycanvas)
				.get(0)
				.getContext("2d");
		}
	}

	luckysheetTableContent.save();
	luckysheetTableContent.scale(Store.devicePixelRatio, Store.devicePixelRatio);

	luckysheetTableContent.clearRect(
		0,
		0,
		Store.luckysheetTableContentHW[0],
		Store.luckysheetTableContentHW[1]
	);

	//表格渲染区域 起止行列下标
	let dataset_row_st, dataset_row_ed, dataset_col_st, dataset_col_ed;

	dataset_row_st = luckysheet_searcharray(Store.visibledatarow, scrollHeight);
	dataset_row_ed = luckysheet_searcharray(
		Store.visibledatarow,
		scrollHeight + drawHeight
	);

	if (dataset_row_st == -1) {
		dataset_row_st = 0;
	}

	dataset_row_st += rowOffsetCell;

	if (dataset_row_ed == -1) {
		dataset_row_ed = Store.visibledatarow.length - 1;
	}

	dataset_row_ed += rowOffsetCell;

	if (dataset_row_ed >= Store.visibledatarow.length) {
		dataset_row_ed = Store.visibledatarow.length - 1;
	}

	dataset_col_st = luckysheet_searcharray(Store.visibledatacolumn, scrollWidth);
	dataset_col_ed = luckysheet_searcharray(
		Store.visibledatacolumn,
		scrollWidth + drawWidth
	);

	if (dataset_col_st == -1) {
		dataset_col_st = 0;
	}

	dataset_col_st += columnOffsetCell;

	if (dataset_col_ed == -1) {
		dataset_col_ed = Store.visibledatacolumn.length - 1;
	}

	dataset_col_ed += columnOffsetCell;

	if (dataset_col_ed >= Store.visibledatacolumn.length) {
		dataset_col_ed = Store.visibledatacolumn.length - 1;
	}

	//表格渲染区域 起止行列坐标
	let fill_row_st, fill_row_ed, fill_col_st, fill_col_ed;

	if (dataset_row_st == 0) {
		fill_row_st = 0;
	} else {
		fill_row_st = Store.visibledatarow[dataset_row_st - 1];
	}

	fill_row_ed = Store.visibledatarow[dataset_row_ed];

	if (dataset_col_st == 0) {
		fill_col_st = 0;
	} else {
		fill_col_st = Store.visibledatacolumn[dataset_col_st - 1];
	}

	fill_col_ed = Store.visibledatacolumn[dataset_col_ed];

	//表格canvas 初始化处理
	luckysheetTableContent.fillStyle = "#ffffff";
	luckysheetTableContent.fillRect(
		offsetLeft - 1,
		offsetTop - 1,
		fill_col_ed - scrollWidth,
		fill_row_ed - scrollHeight
	);
	luckysheetTableContent.font = luckysheetdefaultFont();
	// luckysheetTableContent.textBaseline = "top";
	luckysheetTableContent.fillStyle = luckysheetdefaultstyle.fillStyle;

	//表格渲染区域 非空单元格行列 起止坐标
	let cellupdate = [];
	let mergeCache = {};
	let borderOffset = {};

	let bodrder05 = 0.5; //Default 0.5

	// 钩子函数
	method.createHookFunction(
		"cellAllRenderBefore",
		Store.flowdata,
		sheetFile,
		luckysheetTableContent
	);

	for (let r = dataset_row_st; r <= dataset_row_ed; r++) {
		let start_r;
		if (r == 0) {
			start_r = -scrollHeight - 1;
		} else {
			start_r = Store.visibledatarow[r - 1] - scrollHeight - 1;
		}

		let end_r = Store.visibledatarow[r] - scrollHeight;

		if (
			Store.config["rowhidden"] != null &&
			Store.config["rowhidden"][r] != null
		) {
			continue;
		}

		for (let c = dataset_col_st; c <= dataset_col_ed; c++) {
			let start_c;
			if (c == 0) {
				start_c = -scrollWidth;
			} else {
				start_c = Store.visibledatacolumn[c - 1] - scrollWidth;
			}

			let end_c = Store.visibledatacolumn[c] - scrollWidth;

			if (
				Store.config["colhidden"] != null &&
				Store.config["colhidden"][c] != null
			) {
				continue;
			}

			let firstcolumnlen = Store.defaultcollen;
			if (
				Store.config["columnlen"] != null &&
				Store.config["columnlen"][c] != null
			) {
				firstcolumnlen = Store.config["columnlen"][c];
			}

			if (Store.flowdata[r] != null && Store.flowdata[r][c] != null) {
				let value = Store.flowdata[r][c];

				if (getObjType(value) == "object" && "mc" in value) {
					borderOffset[r + "_" + c] = {
						start_r: start_r,
						start_c: start_c,
						end_r: end_r,
						end_c: end_c,
					};

					if ("rs" in value["mc"]) {
						let key = "r" + r + "c" + c;
						mergeCache[key] = cellupdate.length;
					} else {
						let key = "r" + value["mc"].r + "c" + value["mc"].c;
						let margeMain = cellupdate[mergeCache[key]];

						if (margeMain == null) {
							mergeCache[key] = cellupdate.length;
							cellupdate.push({
								r: r,
								c: c,
								start_c: start_c,
								start_r: start_r,
								end_r: end_r,
								end_c: end_c,
								firstcolumnlen: firstcolumnlen,
							});
						} else {
							if (margeMain.c == c) {
								margeMain.end_r += end_r - start_r - 1;
							}

							if (margeMain.r == r) {
								margeMain.end_c += end_c - start_c;
								margeMain.firstcolumnlen += firstcolumnlen;
							}
						}

						continue;
					}
				}
			} else {
				//空单元格渲染前
				// if(!method.createHookFunction("cellRenderBefore", Store.flowdata[r][c], {
				//     r:r,
				//     c:c,
				//     "start_r": cellsize[1],
				//     "start_c":cellsize[0],
				//     "end_r": cellsize[3],
				//     "end_c": cellsize[2]
				// }, sheetFile,luckysheetTableContent)){ continue; }
			}

			cellupdate.push({
				r: r,
				c: c,
				start_r: start_r,
				start_c: start_c,
				end_r: end_r,
				end_c: end_c,
				firstcolumnlen: firstcolumnlen,
			});
			borderOffset[r + "_" + c] = {
				start_r: start_r,
				start_c: start_c,
				end_r: end_r,
				end_c: end_c,
			};
		}
	}

	//动态数组公式计算
	let dynamicArray_compute = dynamicArrayCompute(
		Store.luckysheetfile[getSheetIndex(Store.currentSheetIndex)]["dynamicArray"]
	);

	//交替颜色计算
	let af_compute = alternateformat.getComputeMap();

	//条件格式计算
	let cf_compute = conditionformat.getComputeMap();

	//表格渲染区域 溢出单元格配置保存
	let cellOverflowMap = getCellOverflowMap(
		luckysheetTableContent,
		dataset_col_st,
		dataset_col_ed,
		dataset_row_st,
		dataset_row_ed
	);

	let mcArr = [];

	for (let cud = 0; cud < cellupdate.length; cud++) {
		let item = cellupdate[cud];
		let r = item.r,
			c = item.c,
			start_r = item.start_r,
			start_c = item.start_c,
			end_r = item.end_r,
			end_c = item.end_c;
		let firstcolumnlen = item.firstcolumnlen;

		if (Store.flowdata[r] == null) {
			continue;
		}

		// //有值单元格渲染前
		// if(!method.createHookFunction("cellRenderBefore", Store.flowdata[r][c], {
		//     r:r,
		//     c:c,
		//     "start_r": cellsize[1],
		//     "start_c":cellsize[0],
		//     "end_r": cellsize[3],
		//     "end_c": cellsize[2]
		// }, sheetFile,luckysheetTableContent)){ continue; }

		if (Store.flowdata[r][c] == null) {
			//空单元格
			nullCellRender(
				r,
				c,
				start_r,
				start_c,
				end_r,
				end_c,
				luckysheetTableContent,
				af_compute,
				cf_compute,
				offsetLeft,
				offsetTop,
				dynamicArray_compute,
				cellOverflowMap,
				dataset_col_st,
				dataset_col_ed,
				scrollHeight,
				scrollWidth,
				bodrder05
			);
		} else {
			let cell = Store.flowdata[r][c];
			let value = null;

			if (typeof cell == "object" && "mc" in cell) {
				mcArr.push(cellupdate[cud]);
				// continue;
			} else {
				value = getRealCellValue(r, c);
			}

			if (value == null || value.toString().length == 0) {
				nullCellRender(
					r,
					c,
					start_r,
					start_c,
					end_r,
					end_c,
					luckysheetTableContent,
					af_compute,
					cf_compute,
					offsetLeft,
					offsetTop,
					dynamicArray_compute,
					cellOverflowMap,
					dataset_col_st,
					dataset_col_ed,
					scrollHeight,
					scrollWidth,
					bodrder05
				);

				//sparklines渲染
				let borderfix = menuButton.borderfix(Store.flowdata, r, c);
				let cellsize = [
					start_c + offsetLeft + borderfix[0],
					start_r + offsetTop + borderfix[1],
					end_c - start_c - 3 + borderfix[2],
					end_r - start_r - 3 - 1 + borderfix[3],
				];
				sparklinesRender(
					r,
					c,
					cellsize[0],
					cellsize[1],
					"luckysheetTableContent",
					luckysheetTableContent
				);
			} else {
				if (r + "_" + c in dynamicArray_compute) {
					//动态数组公式
					value = dynamicArray_compute[r + "_" + c].v;
				}

				cellRender(
					r,
					c,
					start_r,
					start_c,
					end_r,
					end_c,
					value,
					luckysheetTableContent,
					af_compute,
					cf_compute,
					offsetLeft,
					offsetTop,
					dynamicArray_compute,
					cellOverflowMap,
					dataset_col_st,
					dataset_col_ed,
					scrollHeight,
					scrollWidth,
					bodrder05
				);
			}
		}

		// method.createHookFunction("cellRenderAfter", Store.flowdata[r][c], {
		//     r:r,
		//     c:c,
		//     "start_r": start_r,
		//     "start_c": start_c,
		//     "end_r": end_r,
		//     "end_c": end_c
		// }, sheetFile,luckysheetTableContent)
	}

	//合并单元格再处理
	for (let m = 0; m < mcArr.length; m++) {
		let item = mcArr[m];
		let r = item.r,
			c = item.c,
			start_r = item.start_r,
			start_c = item.start_c,
			end_r = item.end_r - 1,
			end_c = item.end_c - 1;
		let firstcolumnlen = item.firstcolumnlen;

		let cell = Store.flowdata[r][c];
		let value = null;

		let margeMaindata = cell["mc"];

		value = getRealCellValue(margeMaindata.r, margeMaindata.c);

		r = margeMaindata.r;
		c = margeMaindata.c;

		let mainCell = Store.flowdata[r][c];

		if (c == 0) {
			start_c = -scrollWidth;
		} else {
			start_c = Store.visibledatacolumn[c - 1] - scrollWidth;
		}

		if (r == 0) {
			start_r = -scrollHeight - 1;
		} else {
			start_r = Store.visibledatarow[r - 1] - scrollHeight - 1;
		}

		end_r = Store.visibledatarow[r + mainCell["mc"].rs - 1] - scrollHeight;
		end_c = Store.visibledatacolumn[c + mainCell["mc"].cs - 1] - scrollWidth;

		if (value == null || value.toString().length == 0) {
			nullCellRender(
				r,
				c,
				start_r,
				start_c,
				end_r,
				end_c,
				luckysheetTableContent,
				af_compute,
				cf_compute,
				offsetLeft,
				offsetTop,
				dynamicArray_compute,
				cellOverflowMap,
				dataset_col_st,
				dataset_col_ed,
				scrollHeight,
				scrollWidth,
				bodrder05,
				true
			);

			//sparklines渲染
			let borderfix = menuButton.borderfix(Store.flowdata, r, c);
			let cellsize = [
				start_c + offsetLeft + borderfix[0],
				start_r + offsetTop + borderfix[1],
				end_c - start_c - 3 + borderfix[2],
				end_r - start_r - 3 - 1 + borderfix[3],
			];
			sparklinesRender(
				r,
				c,
				cellsize[0],
				cellsize[1],
				"luckysheetTableContent",
				luckysheetTableContent
			);
		} else {
			if (r + "_" + c in dynamicArray_compute) {
				//动态数组公式
				value = dynamicArray_compute[r + "_" + c].v;
			}
			cellRender(
				r,
				c,
				start_r,
				start_c,
				end_r,
				end_c,
				value,
				luckysheetTableContent,
				af_compute,
				cf_compute,
				offsetLeft,
				offsetTop,
				dynamicArray_compute,
				cellOverflowMap,
				dataset_col_st,
				dataset_col_ed,
				scrollHeight,
				scrollWidth,
				bodrder05,
				true
			);
		}
	}

	//数据透视表边框渲染
	for (let r = dataset_row_st; r <= dataset_row_ed; r++) {
		let start_r;
		if (r == 0) {
			start_r = -scrollHeight - 1;
		} else {
			start_r = Store.visibledatarow[r - 1] - scrollHeight - 1;
		}

		let end_r = Store.visibledatarow[r] - scrollHeight;

		for (let c = dataset_col_st; c <= dataset_col_ed; c++) {
			let start_c;
			if (c == 0) {
				start_c = -scrollWidth;
			} else {
				start_c = Store.visibledatacolumn[c - 1] - scrollWidth;
			}

			let end_c = Store.visibledatacolumn[c] - scrollWidth;

			//数据透视表
			if (!!Store.luckysheetcurrentisPivotTable && pivotTable.drawPivotTable) {
				if ((c == 0 || c == 5) && r <= 11) {
					luckysheetTableContent.beginPath();
					luckysheetTableContent.moveTo(
						end_c - 2 + bodrder05 + offsetLeft,
						start_r + offsetTop
					);
					luckysheetTableContent.lineTo(
						end_c - 2 + bodrder05 + offsetLeft,
						end_r - 2 + bodrder05 + offsetTop
					);
					luckysheetTableContent.lineWidth = 1;
					luckysheetTableContent.strokeStyle = "#000000";
					luckysheetTableContent.closePath();
					luckysheetTableContent.stroke();
				}

				if ((r == 2 || r == 11) && c <= 5) {
					luckysheetTableContent.beginPath();
					luckysheetTableContent.moveTo(
						start_c - 1 + offsetLeft,
						end_r - 2 + bodrder05 + offsetTop
					);
					luckysheetTableContent.lineTo(
						end_c - 2 + bodrder05 + offsetLeft,
						end_r - 2 + bodrder05 + offsetTop
					);
					luckysheetTableContent.lineWidth = 1;
					luckysheetTableContent.strokeStyle = "#000000";
					luckysheetTableContent.closePath();
					luckysheetTableContent.stroke();
				}

				if (r == 6 && c == 3) {
					luckysheetTableContent.save();
					luckysheetTableContent.font = "bold 30px Arial";
					luckysheetTableContent.fillStyle = "#626675";
					luckysheetTableContent.textAlign = "center";
					luckysheetTableContent.fillText(
						locale().pivotTable.title,
						start_c + (end_c - start_c) / 2 + 4 + offsetLeft,
						start_r + (end_r - start_r) / 2 - 1 + offsetTop
					);
					luckysheetTableContent.restore();
				}
			} else if (!!Store.luckysheetcurrentisPivotTable) {
				if (
					c < pivotTable.pivotTableBoundary[1] &&
					r < pivotTable.pivotTableBoundary[0]
				) {
					luckysheetTableContent.beginPath();
					luckysheetTableContent.moveTo(
						end_c - 2 + bodrder05 + offsetLeft,
						start_r + offsetTop
					);
					luckysheetTableContent.lineTo(
						end_c - 2 + bodrder05 + offsetLeft,
						end_r - 2 + bodrder05 + offsetTop
					);
					luckysheetTableContent.lineWidth = 1;
					luckysheetTableContent.strokeStyle = "#000000";
					luckysheetTableContent.closePath();
					luckysheetTableContent.stroke();

					luckysheetTableContent.beginPath();
					luckysheetTableContent.moveTo(
						start_c - 1 + offsetLeft,
						end_r - 2 + bodrder05 + offsetTop
					);
					luckysheetTableContent.lineTo(
						end_c - 2 + offsetLeft,
						end_r - 2 + bodrder05 + offsetTop
					);
					luckysheetTableContent.lineWidth = 1;
					luckysheetTableContent.strokeStyle = "#000000";
					luckysheetTableContent.closePath();
					luckysheetTableContent.stroke();
				}
			}
		}
	}

	//边框单独渲染
	if (
		Store.config["borderInfo"] != null &&
		Store.config["borderInfo"].length > 0
	) {
		//边框渲染
		let borderLeftRender = function(
			style,
			color,
			start_r,
			start_c,
			end_r,
			end_c,
			offsetLeft,
			offsetTop,
			canvas
		) {
			let linetype = style;

			let m_st = start_c - 2 + bodrder05 + offsetLeft;
			let m_ed = start_r + offsetTop - 1;
			let line_st = start_c - 2 + bodrder05 + offsetLeft;
			let line_ed = end_r - 2 + bodrder05 + offsetTop;
			canvas.save();
			menuButton.setLineDash(
				canvas,
				linetype,
				"v",
				m_st,
				m_ed,
				line_st,
				line_ed
			);

			canvas.strokeStyle = color;

			canvas.stroke();
			canvas.closePath();
			canvas.restore();
		};

		let borderRightRender = function(
			style,
			color,
			start_r,
			start_c,
			end_r,
			end_c,
			offsetLeft,
			offsetTop,
			canvas
		) {
			let linetype = style;

			let m_st = end_c - 2 + bodrder05 + offsetLeft;
			let m_ed = start_r + offsetTop - 1;
			let line_st = end_c - 2 + bodrder05 + offsetLeft;
			let line_ed = end_r - 2 + bodrder05 + offsetTop;
			canvas.save();
			menuButton.setLineDash(
				canvas,
				linetype,
				"v",
				m_st,
				m_ed,
				line_st,
				line_ed
			);

			canvas.strokeStyle = color;

			canvas.stroke();
			canvas.closePath();
			canvas.restore();
		};

		let borderBottomRender = function(
			style,
			color,
			start_r,
			start_c,
			end_r,
			end_c,
			offsetLeft,
			offsetTop,
			canvas
		) {
			let linetype = style;

			let m_st = start_c - 2 + bodrder05 + offsetLeft;
			let m_ed = end_r - 2 + bodrder05 + offsetTop;
			let line_st = end_c - 2 + bodrder05 + offsetLeft;
			let line_ed = end_r - 2 + bodrder05 + offsetTop;
			canvas.save();
			menuButton.setLineDash(
				canvas,
				linetype,
				"h",
				m_st,
				m_ed,
				line_st,
				line_ed
			);

			canvas.strokeStyle = color;

			canvas.stroke();
			canvas.closePath();
			canvas.restore();
		};

		let borderTopRender = function(
			style,
			color,
			start_r,
			start_c,
			end_r,
			end_c,
			offsetLeft,
			offsetTop,
			canvas
		) {
			let linetype = style;

			let m_st = start_c - 2 + bodrder05 + offsetLeft;
			let m_ed = start_r - 1 + bodrder05 + offsetTop;
			let line_st = end_c - 2 + bodrder05 + offsetLeft;
			let line_ed = start_r - 1 + bodrder05 + offsetTop;
			canvas.save();
			menuButton.setLineDash(
				canvas,
				linetype,
				"h",
				m_st,
				m_ed,
				line_st,
				line_ed
			);

			canvas.strokeStyle = color;

			canvas.stroke();
			canvas.closePath();
			canvas.restore();
		};

		let borderInfoCompute = getBorderInfoComputeRange(
			dataset_row_st,
			dataset_row_ed,
			dataset_col_st,
			dataset_col_ed
		);

		for (let x in borderInfoCompute) {
			//let bd_r = x.split("_")[0], bd_c = x.split("_")[1];

			let bd_r = x.substr(0, x.indexOf("_"));
			let bd_c = x.substr(x.indexOf("_") + 1);

			// if(bd_r < dataset_row_st || bd_r > dataset_row_ed || bd_c < dataset_col_st || bd_c > dataset_col_ed){
			//     continue;
			// }

			if (borderOffset[bd_r + "_" + bd_c]) {
				let start_r = borderOffset[bd_r + "_" + bd_c].start_r;
				let start_c = borderOffset[bd_r + "_" + bd_c].start_c;
				let end_r = borderOffset[bd_r + "_" + bd_c].end_r;
				let end_c = borderOffset[bd_r + "_" + bd_c].end_c;

				let cellOverflow_colInObj = cellOverflow_colIn(
					cellOverflowMap,
					bd_r,
					bd_c,
					dataset_col_st,
					dataset_col_ed
				);

				let borderLeft = borderInfoCompute[x].l;
				if (
					borderLeft != null &&
					(!cellOverflow_colInObj.colIn || cellOverflow_colInObj.stc == bd_c)
				) {
					borderLeftRender(
						borderLeft.style,
						borderLeft.color,
						start_r,
						start_c,
						end_r,
						end_c,
						offsetLeft,
						offsetTop,
						luckysheetTableContent
					);
				}

				let borderRight = borderInfoCompute[x].r;
				if (
					borderRight != null &&
					(!cellOverflow_colInObj.colIn || cellOverflow_colInObj.colLast)
				) {
					borderRightRender(
						borderRight.style,
						borderRight.color,
						start_r,
						start_c,
						end_r,
						end_c,
						offsetLeft,
						offsetTop,
						luckysheetTableContent
					);
				}

				let borderTop = borderInfoCompute[x].t;
				if (borderTop != null) {
					borderTopRender(
						borderTop.style,
						borderTop.color,
						start_r,
						start_c,
						end_r,
						end_c,
						offsetLeft,
						offsetTop,
						luckysheetTableContent
					);
				}

				let borderBottom = borderInfoCompute[x].b;
				if (borderBottom != null) {
					borderBottomRender(
						borderBottom.style,
						borderBottom.color,
						start_r,
						start_c,
						end_r,
						end_c,
						offsetLeft,
						offsetTop,
						luckysheetTableContent
					);
				}
			}
		}
	}

	//渲染表格时有尾列时，清除右边灰色区域，防止表格有值溢出
	if (dataset_col_ed == Store.visibledatacolumn.length - 1) {
		luckysheetTableContent.clearRect(
			fill_col_ed - scrollWidth + offsetLeft - 1,
			offsetTop - 1,
			Store.ch_width - Store.visibledatacolumn[dataset_col_ed],
			fill_row_ed - scrollHeight
		);
	}

	luckysheetTableContent.restore();

	Store.measureTextCacheTimeOut = setTimeout(() => {
		Store.measureTextCache = {};
		Store.measureTextCellInfoCache = {};
		Store.cellOverflowMapCache = {};
	}, 100);
}

//sparklines渲染
let sparklinesRender = function(r, c, offsetX, offsetY, canvasid, ctx) {
	if (Store.flowdata[r] == null || Store.flowdata[r][c] == null) {
		return;
	}

	let sparklines = Store.flowdata[r][c].spl;
	if (sparklines != null) {
		if (typeof sparklines == "string") {
			sparklines = new Function("return " + sparklines)();
		}

		if (getObjType(sparklines) == "object") {
			let temp1 = sparklines;
			let x = temp1.offsetX;
			let y = temp1.offsetY;
			x = x == null ? 0 : x;
			y = y == null ? 0 : y;
			luckysheetSparkline.render(
				temp1.shapeseq,
				temp1.shapes,
				offsetX + x,
				offsetY + y,
				temp1.pixelWidth,
				temp1.pixelHeight,
				canvasid,
				ctx
			);
		} else if (
			getObjType(sparklines) == "array" &&
			getObjType(sparklines[0]) == "object"
		) {
			for (let i = 0; i < sparklines.length; i++) {
				let temp1 = sparklines[i];
				let x = temp1.offsetX;
				let y = temp1.offsetY;
				x = x == null ? 0 : x;
				y = y == null ? 0 : y;
				luckysheetSparkline.render(
					temp1.shapeseq,
					temp1.shapes,
					offsetX + x,
					offsetY + y,
					temp1.pixelWidth,
					temp1.pixelHeight,
					canvasid,
					ctx
				);
			}
		}
	}
};

//空白单元格渲染
let nullCellRender = function(
	r,
	c,
	start_r,
	start_c,
	end_r,
	end_c,
	luckysheetTableContent,
	af_compute,
	cf_compute,
	offsetLeft,
	offsetTop,
	dynamicArray_compute,
	cellOverflowMap,
	dataset_col_st,
	dataset_col_ed,
	scrollHeight,
	scrollWidth,
	bodrder05,
	isMerge
) {
	let checksAF = alternateformat.checksAF(r, c, af_compute); //交替颜色
	let checksCF = conditionformat.checksCF(r, c, cf_compute); //条件格式

	let borderfix = menuButton.borderfix(Store.flowdata, r, c);

	//背景色
	let fillStyle = menuButton.checkstatus(Store.flowdata, r, c, "bg");

	if (checksAF != null && checksAF[1] != null) {
		//交替颜色
		fillStyle = checksAF[1];
	}

	if (checksCF != null && checksCF["cellColor"] != null) {
		//条件格式
		fillStyle = checksCF["cellColor"];
	}

	if (Store.flowdata[r][c] != null && Store.flowdata[r][c].tc != null) {
		//标题色
		fillStyle = Store.flowdata[r][c].tc;
	}

	if (fillStyle == null) {
		luckysheetTableContent.fillStyle = "#FFFFFF";
	} else {
		luckysheetTableContent.fillStyle = fillStyle;
	}

	// 这里计算canvas需要绘制的矩形范围时,需要留下原本单元格边框的位置
	// 让 fillRect 绘制矩形的起始xy坐标增加1,绘制长宽减少1

	let cellsize = [
		start_c + offsetLeft + borderfix[0] + 1,
		start_r + offsetTop + borderfix[1] + 1,
		end_c - start_c + borderfix[2] - (!!isMerge ? 1 : 0) - 1,
		end_r - start_r + borderfix[3] - 1,
	];

	//单元格渲染前，考虑到合并单元格会再次渲染一遍，统一放到这里
	if (
		!method.createHookFunction(
			"cellRenderBefore",
			Store.flowdata[r][c],
			{
				r: r,
				c: c,
				start_r: cellsize[1],
				start_c: cellsize[0],
				end_r: cellsize[3] + cellsize[1],
				end_c: cellsize[2] + cellsize[0],
			},
			sheetmanage.getSheetByIndex(),
			luckysheetTableContent
		)
	) {
		return;
	}

	luckysheetTableContent.fillRect(
		cellsize[0],
		cellsize[1],
		cellsize[2],
		cellsize[3]
	);

	if (r + "_" + c in dynamicArray_compute) {
		let value = dynamicArray_compute[r + "_" + c].v;

		luckysheetTableContent.fillStyle = "#000000";
		//文本宽度和高度
		let fontset = luckysheetdefaultFont();
		luckysheetTableContent.font = fontset;

		//水平对齐 (默认为1，左对齐)
		let horizonAlignPos = start_c + 4 + offsetLeft;

		//垂直对齐 (默认为2，下对齐)
		let verticalFixed = browser.luckysheetrefreshfixed();
		let verticalAlignPos = end_r + offsetTop - 2;
		luckysheetTableContent.textBaseline = "bottom";

		luckysheetTableContent.fillText(
			value == null ? "" : value,
			horizonAlignPos,
			verticalAlignPos
		);
	}

	//若单元格有批注
	if (Store.flowdata[r][c] != null && Store.flowdata[r][c].ps != null) {
		let ps_w = 8 * Store.zoomRatio,
			ps_h = 8 * Store.zoomRatio;
		luckysheetTableContent.beginPath();
		luckysheetTableContent.moveTo(
			end_c + offsetLeft - 1 - ps_w,
			start_r + offsetTop
		);
		luckysheetTableContent.lineTo(end_c + offsetLeft - 1, start_r + offsetTop);
		luckysheetTableContent.lineTo(
			end_c + offsetLeft - 1,
			start_r + offsetTop + ps_h
		);
		luckysheetTableContent.fillStyle = "#FC6666";
		luckysheetTableContent.fill();
		luckysheetTableContent.closePath();
	}

	//此单元格 与  溢出单元格关系
	let cellOverflow_colInObj = cellOverflow_colIn(
		cellOverflowMap,
		r,
		c,
		dataset_col_st,
		dataset_col_ed
	);

	//此单元格 为 溢出单元格渲染范围最后一列，绘制溢出单元格内容
	if (cellOverflow_colInObj.colLast) {
		cellOverflowRender(
			cellOverflow_colInObj.rowIndex,
			cellOverflow_colInObj.colIndex,
			cellOverflow_colInObj.stc,
			cellOverflow_colInObj.edc,
			luckysheetTableContent,
			scrollHeight,
			scrollWidth,
			offsetLeft,
			offsetTop,
			af_compute,
			cf_compute
		);
	}

	//即溢出单元格跨此单元格，此单元格不绘制右边框
	if (!cellOverflow_colInObj.colIn || cellOverflow_colInObj.colLast) {
		// 右边框
		// 无论是否有背景色，都默认绘制右边框
		if (!Store.luckysheetcurrentisPivotTable && Store.showGridLines) {
			luckysheetTableContent.beginPath();
			luckysheetTableContent.moveTo(
				end_c + offsetLeft - 2 + bodrder05,
				start_r + offsetTop
			);
			luckysheetTableContent.lineTo(
				end_c + offsetLeft - 2 + bodrder05,
				end_r + offsetTop
			);
			luckysheetTableContent.lineWidth = 1;

			luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
			luckysheetTableContent.stroke();
			luckysheetTableContent.closePath();
		}
	}

	// 下边框
	// 无论是否有背景色，都默认绘制下边框
	if (!Store.luckysheetcurrentisPivotTable && Store.showGridLines) {
		luckysheetTableContent.beginPath();
		luckysheetTableContent.moveTo(
			start_c + offsetLeft - 1,
			end_r + offsetTop - 2 + bodrder05
		);
		luckysheetTableContent.lineTo(
			end_c + offsetLeft - 1,
			end_r + offsetTop - 2 + bodrder05
		);
		luckysheetTableContent.lineWidth = 1;

		luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
		luckysheetTableContent.stroke();
		luckysheetTableContent.closePath();
	}

	// 单元格渲染后
	method.createHookFunction(
		"cellRenderAfter",
		Store.flowdata[r][c],
		{
			r: r,
			c: c,
			start_r: cellsize[1],
			start_c: cellsize[0],
			end_r: cellsize[3] + cellsize[1],
			end_c: cellsize[2] + cellsize[0],
		},
		sheetmanage.getSheetByIndex(),
		luckysheetTableContent
	);
};

let cellRender = function(
	r,
	c,
	start_r,
	start_c,
	end_r,
	end_c,
	value,
	luckysheetTableContent,
	af_compute,
	cf_compute,
	offsetLeft,
	offsetTop,
	dynamicArray_compute,
	cellOverflowMap,
	dataset_col_st,
	dataset_col_ed,
	scrollHeight,
	scrollWidth,
	bodrder05,
	isMerge
) {
	let cell = Store.flowdata[r][c];
	let cellWidth = end_c - start_c - 2;
	let cellHeight = end_r - start_r - 2;
	let space_width = 2,
		space_height = 2; //宽高方向 间隙

	//水平对齐
	let horizonAlign = menuButton.checkstatus(Store.flowdata, r, c, "ht");
	//垂直对齐
	let verticalAlign = menuButton.checkstatus(Store.flowdata, r, c, "vt");

	//交替颜色
	let checksAF = alternateformat.checksAF(r, c, af_compute);
	//条件格式
	let checksCF = conditionformat.checksCF(r, c, cf_compute);

	//单元格 背景颜色
	let fillStyle = menuButton.checkstatus(Store.flowdata, r, c, "bg");
	if (checksAF != null && checksAF[1] != null) {
		//若单元格有交替颜色 背景颜色
		fillStyle = checksAF[1];
	}
	if (checksCF != null && checksCF["cellColor"] != null) {
		//若单元格有条件格式 背景颜色
		fillStyle = checksCF["cellColor"];
	}
	// luckysheetTableContent.textBaseline = 'top';
	if (fillStyle == null) {
		luckysheetTableContent.fillStyle = "#FFFFFF";
	} else {
		luckysheetTableContent.fillStyle = fillStyle;
	}

	let borderfix = menuButton.borderfix(Store.flowdata, r, c);

	// 这里计算canvas需要绘制的矩形范围时,需要留下原本单元格边框的位置
	// 让 fillRect 绘制矩形的起始xy坐标增加1,绘制长宽减少1

	let cellsize = [
		start_c + offsetLeft + borderfix[0] + 1,
		start_r + offsetTop + borderfix[1] + 1,
		end_c - start_c + borderfix[2] - (!!isMerge ? 1 : 0) - 1,
		end_r - start_r + borderfix[3] + 1,
	];

	//单元格渲染前，考虑到合并单元格会再次渲染一遍，统一放到这里
	if (
		!method.createHookFunction(
			"cellRenderBefore",
			Store.flowdata[r][c],
			{
				r: r,
				c: c,
				start_r: cellsize[1],
				start_c: cellsize[0],
				end_r: cellsize[3] + cellsize[1],
				end_c: cellsize[2] + cellsize[0],
			},
			sheetmanage.getSheetByIndex(),
			luckysheetTableContent
		)
	) {
		return;
	}

	luckysheetTableContent.fillRect(
		cellsize[0],
		cellsize[1],
		cellsize[2],
		cellsize[3]
	);

	let dataVerification = dataVerificationCtrl.dataVerification;

	if (
		dataVerification != null &&
		dataVerification[r + "_" + c] != null &&
		!dataVerificationCtrl.validateCellData(value, dataVerification[r + "_" + c])
	) {
		//单元格左上角红色小三角标示
		let dv_w = 5 * Store.zoomRatio,
			dv_h = 5 * Store.zoomRatio; //红色小三角宽高

		luckysheetTableContent.beginPath();
		luckysheetTableContent.moveTo(start_c + offsetLeft, start_r + offsetTop);
		luckysheetTableContent.lineTo(
			start_c + offsetLeft + dv_w,
			start_r + offsetTop
		);
		luckysheetTableContent.lineTo(
			start_c + offsetLeft,
			start_r + offsetTop + dv_h
		);
		luckysheetTableContent.fillStyle = "#FC6666";
		luckysheetTableContent.fill();
		luckysheetTableContent.closePath();
	}

	//若单元格有批注（单元格右上角红色小三角标示）
	if (cell.ps != null) {
		let ps_w = 8 * Store.zoomRatio,
			ps_h = 8 * Store.zoomRatio; //红色小三角宽高

		luckysheetTableContent.beginPath();
		luckysheetTableContent.moveTo(
			end_c + offsetLeft - ps_w,
			start_r + offsetTop
		);
		luckysheetTableContent.lineTo(end_c + offsetLeft, start_r + offsetTop);
		luckysheetTableContent.lineTo(
			end_c + offsetLeft,
			start_r + offsetTop + ps_h
		);
		luckysheetTableContent.fillStyle = "#FC6666";
		luckysheetTableContent.fill();
		luckysheetTableContent.closePath();
	}

	//若单元格强制为字符串，则显示绿色小三角
	if (cell.qp == 1 && isRealNum(cell.v)) {
		let ps_w = 6 * Store.zoomRatio,
			ps_h = 6 * Store.zoomRatio; //红色小三角宽高

		luckysheetTableContent.beginPath();
		luckysheetTableContent.moveTo(
			start_c + offsetLeft + ps_w - 1,
			start_r + offsetTop
		);
		luckysheetTableContent.lineTo(
			start_c + offsetLeft - 1,
			start_r + offsetTop
		);
		luckysheetTableContent.lineTo(
			start_c + offsetLeft - 1,
			start_r + offsetTop + ps_h
		);
		luckysheetTableContent.fillStyle = "#487f1e";
		luckysheetTableContent.fill();
		luckysheetTableContent.closePath();
	}

	//溢出单元格
	let cellOverflow_bd_r_render = true; //溢出单元格右边框是否需要绘制
	let cellOverflow_colInObj = cellOverflow_colIn(
		cellOverflowMap,
		r,
		c,
		dataset_col_st,
		dataset_col_ed
	);

	if (cell.tb == "1" && cellOverflow_colInObj.colIn) {
		//此单元格 为 溢出单元格渲染范围最后一列，绘制溢出单元格内容
		if (cellOverflow_colInObj.colLast) {
			cellOverflowRender(
				cellOverflow_colInObj.rowIndex,
				cellOverflow_colInObj.colIndex,
				cellOverflow_colInObj.stc,
				cellOverflow_colInObj.edc,
				luckysheetTableContent,
				scrollHeight,
				scrollWidth,
				offsetLeft,
				offsetTop,
				af_compute,
				cf_compute
			);
		} else {
			cellOverflow_bd_r_render = false;
		}
	}
	//数据验证 复选框
	else if (
		dataVerification != null &&
		dataVerification[r + "_" + c] != null &&
		dataVerification[r + "_" + c].type == "checkbox"
	) {
		let pos_x = start_c + offsetLeft;
		let pos_y = start_r + offsetTop + 1;

		luckysheetTableContent.save();
		luckysheetTableContent.beginPath();
		luckysheetTableContent.rect(pos_x, pos_y, cellWidth, cellHeight);
		luckysheetTableContent.clip();
		luckysheetTableContent.scale(Store.zoomRatio, Store.zoomRatio);

		let measureText = getMeasureText(value, luckysheetTableContent);
		let textMetrics = measureText.width + 14;
		let oneLineTextHeight =
			measureText.actualBoundingBoxDescent +
			measureText.actualBoundingBoxAscent;

		let horizonAlignPos = pos_x + space_width; //默认为1，左对齐
		if (horizonAlign == "0") {
			//居中对齐
			horizonAlignPos = pos_x + cellWidth / 2 - textMetrics / 2;
		} else if (horizonAlign == "2") {
			//右对齐
			horizonAlignPos = pos_x + cellWidth - space_width - textMetrics;
		}

		let verticalCellHeight =
			cellHeight > oneLineTextHeight ? cellHeight : oneLineTextHeight;

		let verticalAlignPos_text = pos_y + verticalCellHeight - space_height; //文本垂直方向基准线
		luckysheetTableContent.textBaseline = "bottom";
		let verticalAlignPos_checkbox =
			verticalAlignPos_text - 13 * Store.zoomRatio;

		if (verticalAlign == "0") {
			//居中对齐
			verticalAlignPos_text = pos_y + verticalCellHeight / 2;
			luckysheetTableContent.textBaseline = "middle";
			verticalAlignPos_checkbox = verticalAlignPos_text - 6 * Store.zoomRatio;
		} else if (verticalAlign == "1") {
			//上对齐
			verticalAlignPos_text = pos_y + space_height;
			luckysheetTableContent.textBaseline = "top";
			verticalAlignPos_checkbox = verticalAlignPos_text + 1 * Store.zoomRatio;
		}

		horizonAlignPos = horizonAlignPos / Store.zoomRatio;
		verticalAlignPos_text = verticalAlignPos_text / Store.zoomRatio;
		verticalAlignPos_checkbox = verticalAlignPos_checkbox / Store.zoomRatio;

		//复选框
		luckysheetTableContent.lineWidth = 1;
		luckysheetTableContent.strokeStyle = "#000";
		luckysheetTableContent.strokeRect(
			horizonAlignPos,
			verticalAlignPos_checkbox,
			10,
			10
		);

		if (dataVerification[r + "_" + c].checked) {
			luckysheetTableContent.beginPath();
			luckysheetTableContent.lineTo(
				horizonAlignPos + 1,
				verticalAlignPos_checkbox + 6
			);
			luckysheetTableContent.lineTo(
				horizonAlignPos + 4,
				verticalAlignPos_checkbox + 9
			);
			luckysheetTableContent.lineTo(
				horizonAlignPos + 9,
				verticalAlignPos_checkbox + 2
			);
			luckysheetTableContent.stroke();
			luckysheetTableContent.closePath();
		}

		//文本
		luckysheetTableContent.fillStyle = menuButton.checkstatus(
			Store.flowdata,
			r,
			c,
			"fc"
		);
		luckysheetTableContent.fillText(
			value == null ? "" : value,
			horizonAlignPos + 14,
			verticalAlignPos_text
		);

		luckysheetTableContent.restore();
	} else {
		//若单元格有条件格式数据条
		if (
			checksCF != null &&
			checksCF["dataBar"] != null &&
			checksCF["dataBar"]["valueLen"] &&
			checksCF["dataBar"]["valueLen"].toString() !== "NaN"
		) {
			let x = start_c + offsetLeft + space_width;
			let y = start_r + offsetTop + space_height;
			let w = cellWidth - space_width * 2;
			let h = cellHeight - space_height * 2;

			let valueType = checksCF["dataBar"]["valueType"];
			let valueLen = checksCF["dataBar"]["valueLen"];
			let format = checksCF["dataBar"]["format"];

			if (valueType == "minus") {
				//负数
				let minusLen = checksCF["dataBar"]["minusLen"];

				if (format.length > 1) {
					//渐变
					let my_gradient = luckysheetTableContent.createLinearGradient(
						x + w * minusLen * (1 - valueLen),
						y,
						x + w * minusLen,
						y
					);
					my_gradient.addColorStop(0, "#ffffff");
					my_gradient.addColorStop(1, "#ff0000");

					luckysheetTableContent.fillStyle = my_gradient;
				} else {
					//单色
					luckysheetTableContent.fillStyle = "#ff0000";
				}

				luckysheetTableContent.fillRect(
					x + w * minusLen * (1 - valueLen),
					y,
					w * minusLen * valueLen,
					h
				);

				luckysheetTableContent.beginPath();
				luckysheetTableContent.moveTo(x + w * minusLen * (1 - valueLen), y);
				luckysheetTableContent.lineTo(x + w * minusLen * (1 - valueLen), y + h);
				luckysheetTableContent.lineTo(x + w * minusLen, y + h);
				luckysheetTableContent.lineTo(x + w * minusLen, y);
				luckysheetTableContent.lineTo(x + w * minusLen * (1 - valueLen), y);
				luckysheetTableContent.lineWidth = 1;
				luckysheetTableContent.strokeStyle = "#ff0000";
				luckysheetTableContent.stroke();
				luckysheetTableContent.closePath();
			} else if (valueType == "plus") {
				//正数
				let plusLen = checksCF["dataBar"]["plusLen"];

				if (plusLen == 1) {
					if (format.length > 1) {
						//渐变
						let my_gradient = luckysheetTableContent.createLinearGradient(
							x,
							y,
							x + w * valueLen,
							y
						);
						my_gradient.addColorStop(0, format[0]);
						my_gradient.addColorStop(1, format[1]);

						luckysheetTableContent.fillStyle = my_gradient;
					} else {
						//单色
						luckysheetTableContent.fillStyle = format[0];
					}

					luckysheetTableContent.fillRect(x, y, w * valueLen, h);

					luckysheetTableContent.beginPath();
					luckysheetTableContent.moveTo(x, y);
					luckysheetTableContent.lineTo(x, y + h);
					luckysheetTableContent.lineTo(x + w * valueLen, y + h);
					luckysheetTableContent.lineTo(x + w * valueLen, y);
					luckysheetTableContent.lineTo(x, y);
					luckysheetTableContent.lineWidth = 1;
					luckysheetTableContent.strokeStyle = format[0];
					luckysheetTableContent.stroke();
					luckysheetTableContent.closePath();
				} else {
					let minusLen = checksCF["dataBar"]["minusLen"];

					if (format.length > 1) {
						//渐变
						let my_gradient = luckysheetTableContent.createLinearGradient(
							x + w * minusLen,
							y,
							x + w * minusLen + w * plusLen * valueLen,
							y
						);
						my_gradient.addColorStop(0, format[0]);
						my_gradient.addColorStop(1, format[1]);

						luckysheetTableContent.fillStyle = my_gradient;
					} else {
						//单色
						luckysheetTableContent.fillStyle = format[0];
					}

					luckysheetTableContent.fillRect(
						x + w * minusLen,
						y,
						w * plusLen * valueLen,
						h
					);

					luckysheetTableContent.beginPath();
					luckysheetTableContent.moveTo(x + w * minusLen, y);
					luckysheetTableContent.lineTo(x + w * minusLen, y + h);
					luckysheetTableContent.lineTo(
						x + w * minusLen + w * plusLen * valueLen,
						y + h
					);
					luckysheetTableContent.lineTo(
						x + w * minusLen + w * plusLen * valueLen,
						y
					);
					luckysheetTableContent.lineTo(x + w * minusLen, y);
					luckysheetTableContent.lineWidth = 1;
					luckysheetTableContent.strokeStyle = format[0];
					luckysheetTableContent.stroke();
					luckysheetTableContent.closePath();
				}
			}
		}

		let pos_x = start_c + offsetLeft;
		let pos_y = start_r + offsetTop + 1;

		luckysheetTableContent.save();
		luckysheetTableContent.beginPath();
		luckysheetTableContent.rect(pos_x, pos_y, cellWidth, cellHeight);
		luckysheetTableContent.clip();
		luckysheetTableContent.scale(Store.zoomRatio, Store.zoomRatio);

		let textInfo = getCellTextInfo(cell, luckysheetTableContent, {
			cellWidth: cellWidth,
			cellHeight: cellHeight,
			space_width: space_width,
			space_height: space_height,
			r: r,
			c: c,
		});

		//若单元格有条件格式图标集
		if (
			checksCF != null &&
			checksCF["icons"] != null &&
			textInfo.type == "plain"
		) {
			let l = checksCF["icons"]["left"];
			let t = checksCF["icons"]["top"];

			let value = textInfo.values[0];
			let horizonAlignPos = pos_x + value.left;
			let verticalAlignPos = pos_y + value.top - textInfo.textHeightAll;

			if (verticalAlign == "0") {
				//居中对齐
				verticalAlignPos = pos_y + cellHeight / 2 - textInfo.textHeightAll / 2;
			} else if (verticalAlign == "1") {
				//上对齐
				verticalAlignPos = pos_y;
			} else if (verticalAlign == "2") {
				//下对齐
				verticalAlignPos = verticalAlignPos - textInfo.desc;
			}

			verticalAlignPos = verticalAlignPos / Store.zoomRatio;
			horizonAlignPos = horizonAlignPos / Store.zoomRatio;

			luckysheetTableContent.drawImage(
				luckysheet_CFiconsImg,
				l * 42,
				t * 32,
				32,
				32,
				pos_x / Store.zoomRatio,
				verticalAlignPos,
				textInfo.textHeightAll / Store.zoomRatio,
				textInfo.textHeightAll / Store.zoomRatio
			);

			if (horizonAlign != "0" && horizonAlign != "2") {
				//左对齐时 文本渲染空出一个图标的距离
				horizonAlignPos =
					horizonAlignPos + textInfo.textHeightAll / Store.zoomRatio;
			}
		}

		//单元格 文本颜色
		luckysheetTableContent.fillStyle = menuButton.checkstatus(
			Store.flowdata,
			r,
			c,
			"fc"
		);

		//若单元格有交替颜色 文本颜色
		if (checksAF != null && checksAF[0] != null) {
			luckysheetTableContent.fillStyle = checksAF[0];
		}
		//若单元格有条件格式 文本颜色
		if (checksCF != null && checksCF["textColor"] != null) {
			luckysheetTableContent.fillStyle = checksCF["textColor"];
		}

		//若单元格格式为自定义数字格式（[red]） 文本颜色为红色
		if (
			cell.ct &&
			cell.ct.fa &&
			cell.ct.fa.indexOf("[Red]") > -1 &&
			cell.ct.t == "n" &&
			cell.v < 0
		) {
			luckysheetTableContent.fillStyle = "#ff0000";
		}

		cellTextRender(textInfo, luckysheetTableContent, {
			pos_x: pos_x,
			pos_y: pos_y,
		});

		luckysheetTableContent.restore();
	}

	if (cellOverflow_bd_r_render) {
		// 右边框
		// 无论是否有背景色，都默认绘制右边框
		if (!Store.luckysheetcurrentisPivotTable && Store.showGridLines) {
			luckysheetTableContent.beginPath();
			luckysheetTableContent.moveTo(
				end_c + offsetLeft - 2 + bodrder05,
				start_r + offsetTop
			);
			luckysheetTableContent.lineTo(
				end_c + offsetLeft - 2 + bodrder05,
				end_r + offsetTop
			);
			luckysheetTableContent.lineWidth = 1;
			luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
			luckysheetTableContent.stroke();
			luckysheetTableContent.closePath();
		}
	}

	// 下边框
	// 无论是否有背景色，都默认绘制下边框
	if (!Store.luckysheetcurrentisPivotTable && Store.showGridLines) {
		luckysheetTableContent.beginPath();
		luckysheetTableContent.moveTo(
			start_c + offsetLeft - 1,
			end_r + offsetTop - 2 + bodrder05
		);
		luckysheetTableContent.lineTo(
			end_c + offsetLeft - 1,
			end_r + offsetTop - 2 + bodrder05
		);
		luckysheetTableContent.lineWidth = 1;
		luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
		luckysheetTableContent.stroke();
		luckysheetTableContent.closePath();
	}

	// 单元格渲染后
	method.createHookFunction(
		"cellRenderAfter",
		Store.flowdata[r][c],
		{
			r: r,
			c: c,
			start_r: cellsize[1],
			start_c: cellsize[0],
			end_r: cellsize[3] + cellsize[1],
			end_c: cellsize[2] + cellsize[0],
		},
		sheetmanage.getSheetByIndex(),
		luckysheetTableContent
	);
};

//溢出单元格渲染
let cellOverflowRender = function(
	r,
	c,
	stc,
	edc,
	luckysheetTableContent,
	scrollHeight,
	scrollWidth,
	offsetLeft,
	offsetTop,
	af_compute,
	cf_compute
) {
	//溢出单元格 起止行列坐标
	let start_r;
	if (r == 0) {
		start_r = -scrollHeight - 1;
	} else {
		start_r = Store.visibledatarow[r - 1] - scrollHeight - 1;
	}

	let end_r = Store.visibledatarow[r] - scrollHeight;

	let start_c;
	if (stc == 0) {
		start_c = -scrollWidth;
	} else {
		start_c = Store.visibledatacolumn[stc - 1] - scrollWidth;
	}

	let end_c = Store.visibledatacolumn[edc] - scrollWidth;

	//
	let cell = Store.flowdata[r][c];
	let cellWidth = end_c - start_c - 2;
	let cellHeight = end_r - start_r - 2;
	let space_width = 2,
		space_height = 2; //宽高方向 间隙

	let pos_x = start_c + offsetLeft;
	let pos_y = start_r + offsetTop + 1;

	let fontset = luckysheetfontformat(cell);
	luckysheetTableContent.font = fontset;

	luckysheetTableContent.save();
	luckysheetTableContent.beginPath();
	luckysheetTableContent.rect(pos_x, pos_y, cellWidth, cellHeight);
	luckysheetTableContent.clip();
	luckysheetTableContent.scale(Store.zoomRatio, Store.zoomRatio);

	let textInfo = getCellTextInfo(cell, luckysheetTableContent, {
		cellWidth: cellWidth,
		cellHeight: cellHeight,
		space_width: space_width,
		space_height: space_height,
		r: r,
		c: c,
	});

	//交替颜色
	let checksAF = alternateformat.checksAF(r, c, af_compute);
	//条件格式
	let checksCF = conditionformat.checksCF(r, c, cf_compute);

	//单元格 文本颜色
	luckysheetTableContent.fillStyle = menuButton.checkstatus(
		Store.flowdata,
		r,
		c,
		"fc"
	);

	//若单元格有交替颜色 文本颜色
	if (checksAF != null && checksAF[0] != null) {
		luckysheetTableContent.fillStyle = checksAF[0];
	}
	//若单元格有条件格式 文本颜色
	if (checksCF != null && checksCF["textColor"] != null) {
		luckysheetTableContent.fillStyle = checksCF["textColor"];
	}

	cellTextRender(textInfo, luckysheetTableContent, {
		pos_x: pos_x,
		pos_y: pos_y,
	});

	luckysheetTableContent.restore();
};

//获取表格渲染范围 溢出单元格
function getCellOverflowMap(canvas, col_st, col_ed, row_st, row_end) {
	let map = {};

	let data = Store.flowdata;

	for (let r = row_st; r <= row_end; r++) {
		if (data[r] == null) {
			continue;
		}

		if (Store.cellOverflowMapCache[r] != null) {
			map[r] = Store.cellOverflowMapCache[r];
			continue;
		}

		let hasCellOver = false;

		for (let c = 0; c < data[r].length; c++) {
			let cell = data[r][c];

			// if(Store.cellOverflowMapCache[r + '_' + c]!=null){
			//     map[r + '_' + c] = Store.cellOverflowMapCache[r + '_' + c];
			//     continue;
			// }

			if (
				Store.config["colhidden"] != null &&
				Store.config["colhidden"][c] != null
			) {
				continue;
			}

			if (
				cell != null &&
				(!isRealNull(cell.v) || isInlineStringCell(cell)) &&
				cell.mc == null &&
				cell.tb == "1"
			) {
				//水平对齐
				let horizonAlign = menuButton.checkstatus(data, r, c, "ht");

				let textMetricsObj = getCellTextInfo(cell, canvas, {
					r: r,
					c: c,
				});
				let textMetrics = 0;
				if (textMetricsObj != null) {
					textMetrics = textMetricsObj.textWidthAll;
				}

				//canvas.measureText(value).width;

				let start_c = c - 1 < 0 ? 0 : Store.visibledatacolumn[c - 1];
				let end_c = Store.visibledatacolumn[c];

				let stc, edc;

				if (end_c - start_c < textMetrics) {
					if (horizonAlign == "0") {
						//居中对齐
						let trace_forward = cellOverflow_trace(
							r,
							c,
							c - 1,
							"forward",
							horizonAlign,
							textMetrics
						);
						let trace_backward = cellOverflow_trace(
							r,
							c,
							c + 1,
							"backward",
							horizonAlign,
							textMetrics
						);

						if (trace_forward.success) {
							stc = trace_forward.c;
						} else {
							stc = trace_forward.c + 1;
						}

						if (trace_backward.success) {
							edc = trace_backward.c;
						} else {
							edc = trace_backward.c - 1;
						}
					} else if (horizonAlign == "1") {
						//左对齐
						let trace = cellOverflow_trace(
							r,
							c,
							c + 1,
							"backward",
							horizonAlign,
							textMetrics
						);
						stc = c;

						if (trace.success) {
							edc = trace.c;
						} else {
							edc = trace.c - 1;
						}
					} else if (horizonAlign == "2") {
						//右对齐
						let trace = cellOverflow_trace(
							r,
							c,
							c - 1,
							"forward",
							horizonAlign,
							textMetrics
						);
						edc = c;

						if (trace.success) {
							stc = trace.c;
						} else {
							stc = trace.c + 1;
						}
					}
				} else {
					stc = c;
					edc = c;
				}

				// if(((stc >= col_st && stc <= col_ed) || (edc >= col_st && edc <= col_ed)) && stc < edc){
				if ((stc <= col_ed || edc >= col_st) && stc < edc) {
					let item = {
						r: r,
						stc: stc,
						edc: edc,
					};

					if (map[r] == null) {
						map[r] = {};
					}

					map[r][c] = item;

					// Store.cellOverflowMapCache[r + '_' + c] = item;

					hasCellOver = true;
				}
			}
		}

		if (hasCellOver) {
			Store.cellOverflowMapCache[r] = map[r];
		}
	}

	return map;
}

function cellOverflow_trace(
	r,
	curC,
	traceC,
	traceDir,
	horizonAlign,
	textMetrics
) {
	let data = Store.flowdata;

	//追溯单元格列超出数组范围 则追溯终止
	if (traceDir == "forward" && traceC < 0) {
		return {
			success: false,
			r: r,
			c: traceC,
		};
	}

	if (traceDir == "backward" && traceC > data[r].length - 1) {
		return {
			success: false,
			r: r,
			c: traceC,
		};
	}

	//追溯单元格是 非空单元格或合并单元格 则追溯终止
	let cell = data[r][traceC];
	if (cell != null && (!isRealNull(cell.v) || cell.mc != null)) {
		return {
			success: false,
			r: r,
			c: traceC,
		};
	}

	let start_curC = curC - 1 < 0 ? 0 : Store.visibledatacolumn[curC - 1];
	let end_curC = Store.visibledatacolumn[curC];

	let w = textMetrics - (end_curC - start_curC);

	if (horizonAlign == "0") {
		//居中对齐
		start_curC -= w / 2;
		end_curC += w / 2;
	} else if (horizonAlign == "1") {
		//左对齐
		end_curC += w;
	} else if (horizonAlign == "2") {
		//右对齐
		start_curC -= w;
	}

	let start_traceC = traceC - 1 < 0 ? 0 : Store.visibledatacolumn[traceC - 1];
	let end_traceC = Store.visibledatacolumn[traceC];

	if (traceDir == "forward") {
		if (start_curC < start_traceC) {
			return cellOverflow_trace(
				r,
				curC,
				traceC - 1,
				traceDir,
				horizonAlign,
				textMetrics
			);
		} else if (start_curC < end_traceC) {
			return {
				success: true,
				r: r,
				c: traceC,
			};
		} else {
			return {
				success: false,
				r: r,
				c: traceC,
			};
		}
	}

	if (traceDir == "backward") {
		if (end_curC > end_traceC) {
			return cellOverflow_trace(
				r,
				curC,
				traceC + 1,
				traceDir,
				horizonAlign,
				textMetrics
			);
		} else if (end_curC > start_traceC) {
			return {
				success: true,
				r: r,
				c: traceC,
			};
		} else {
			return {
				success: false,
				r: r,
				c: traceC,
			};
		}
	}
}

function cellOverflow_colIn(map, r, c, col_st, col_ed) {
	let colIn = false, //此单元格 是否在 某个溢出单元格的渲染范围
		colLast = false, //此单元格 是否是 某个溢出单元格的渲染范围的最后一列
		rowIndex, //溢出单元格 行下标
		colIndex, //溢出单元格 列下标
		stc,
		edc;

	for (let rkey in map) {
		for (let ckey in map[rkey]) {
			rowIndex = rkey;
			colIndex = ckey;
			// rowIndex = key.substr(0, key.indexOf('_'));
			// colIndex = key.substr(key.indexOf('_') + 1);
			let mapItem = map[rkey][ckey];
			stc = mapItem.stc;
			edc = mapItem.edc;

			if (rowIndex == r) {
				if (c >= stc && c <= edc) {
					colIn = true;

					if (c == edc || c == col_ed) {
						colLast = true;
						break;
					}
				}
			}
		}

		if (colLast) {
			break;
		}
	}

	return {
		colIn: colIn,
		colLast: colLast,
		rowIndex: rowIndex,
		colIndex: colIndex,
		stc: stc,
		edc: edc,
	};
}

function cellTextRender(textInfo, ctx, option) {
	if (textInfo == null) {
		return;
	}
	let values = textInfo.values;
	let pos_x = option.pos_x,
		pos_y = option.pos_y;
	if (values == null) {
		return;
	}
	// console.log(textInfo, pos_x, pos_y, values[0].width, values[0].left, ctx);

	// for(let i=0;i<values.length;i++){
	//     let word = values[i];
	//     ctx.font = word.style;
	//     ctx.fillText(word.content, (pos_x + word.left)/Store.zoomRatio, (pos_y+word.top)/Store.zoomRatio);
	// }

	// ctx.fillStyle = "rgba(255,255,0,0.2)";
	// ctx.fillRect((pos_x + values[0].left)/Store.zoomRatio, (pos_y+values[0].top-values[0].asc)/Store.zoomRatio, textInfo.textWidthAll, textInfo.textHeightAll)

	if (textInfo.rotate != 0 && textInfo.type != "verticalWrap") {
		ctx.save();
		ctx.translate(
			(pos_x + textInfo.textLeftAll) / Store.zoomRatio,
			(pos_y + textInfo.textTopAll) / Store.zoomRatio
		);
		ctx.rotate((-textInfo.rotate * Math.PI) / 180);
		ctx.translate(
			-(textInfo.textLeftAll + pos_x) / Store.zoomRatio,
			-(pos_y + textInfo.textTopAll) / Store.zoomRatio
		);
	}

	// ctx.fillStyle = "rgb(0,0,0)";
	for (let i = 0; i < values.length; i++) {
		let word = values[i];
		if (word.inline === true && word.style != null) {
			ctx.font = word.style.fontset;
			ctx.fillStyle = word.style.fc;
		} else {
			ctx.font = word.style;
		}

		// 暂时未排查到word.content第一次会是object，先做下判断来渲染，后续找到问题再复原
		let txt = typeof word.content === "object" ? word.content.m : word.content;
		ctx.fillText(
			txt,
			(pos_x + word.left) / Store.zoomRatio,
			(pos_y + word.top) / Store.zoomRatio
		);

		if (word.cancelLine != null) {
			let c = word.cancelLine;
			ctx.beginPath();
			ctx.moveTo(
				Math.floor((pos_x + c.startX) / Store.zoomRatio) + 0.5,
				Math.floor((pos_y + c.startY) / Store.zoomRatio) + 0.5
			);
			ctx.lineTo(
				Math.floor((pos_x + c.endX) / Store.zoomRatio) + 0.5,
				Math.floor((pos_y + c.endY) / Store.zoomRatio) + 0.5
			);
			ctx.lineWidth = Math.floor(c.fs / 9);
			ctx.strokeStyle = ctx.fillStyle;
			ctx.stroke();
			ctx.closePath();
		}

		if (word.underLine != null) {
			let underLines = word.underLine;
			for (let a = 0; a < underLines.length; a++) {
				let item = underLines[a];
				ctx.beginPath();
				ctx.moveTo(
					Math.floor((pos_x + item.startX) / Store.zoomRatio) + 0.5,
					Math.floor((pos_y + item.startY) / Store.zoomRatio)
				);
				ctx.lineTo(
					Math.floor((pos_x + item.endX) / Store.zoomRatio) + 0.5,
					Math.floor((pos_y + item.endY) / Store.zoomRatio) + 0.5
				);
				ctx.lineWidth = Math.floor(item.fs / 9);
				ctx.strokeStyle = ctx.fillStyle;
				ctx.stroke();
				ctx.closePath();
			}
		}
	}
	// ctx.fillStyle = "rgba(0,0,0,0.2)";
	// ctx.fillRect((pos_x + values[0].left)/Store.zoomRatio, (pos_y+values[0].top-values[0].asc)/Store.zoomRatio, textInfo.textWidthAll, textInfo.textHeightAll)
	// ctx.fillStyle = "rgba(255,0,0,1)";
	// ctx.fillRect(pos_x+textInfo.textLeftAll-2, pos_y+textInfo.textTopAll-2, 4,4);
	if (textInfo.rotate != 0 && textInfo.type != "verticalWrap") {
		ctx.restore();
	}
}

export {
	luckysheetDrawgridRowTitle,
	luckysheetDrawgridColumnTitle,
	luckysheetDrawMain,
};
